This a partial patch -- you're expected to hand-munge the code.

The WFM detector in most Amateur Equipment is set to the American
standard (100 kHz deviation and channel spacing, 75 us de-emp, etc.)
Australia has a nice Classical Music FM station which certainly benefits
from our local parameters, even if the Quanie has a tinny little 1 inch
speaker..

--
Chris Baird,, <chris.j.baird@gmail.com> June 2024.



diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/Makefile /home/cjb/uvk2cjb/Makefile
--- uv-k5-firmware-custom/Makefile	2024-06-23 14:06:24.069184668 +1000
+++ /home/cjb/uvk2cjb/Makefile	2024-06-01 17:37:37.418261807 +1000
@@ -1,3 +1,4 @@

 ENABLE_AIRCOPY                ?= 0
+ENABLE_FMRADIO                ?= 1
 ENABLE_NOAA                   ?= 0


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/app/fm.c /home/cjb/uvk2cjb/app/fm.c
--- uv-k5-firmware-custom/app/fm.c	2024-06-23 14:06:24.069184668 +1000
+++ /home/cjb/uvk2cjb/app/fm.c	2024-05-31 12:22:31.611591735 +1000
@@ -148,7 +148,7 @@

         gFM_ScanState = Step;

-        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
 }

@@ -161,6 +161,6 @@

         FM_ConfigureChannelState();
-        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
         SETTINGS_SaveFM();

         gFmPlayCountdown_10ms = 0;

@@ -272,6 +272,6 @@

                                 gEeprom.FM_FrequencyPlaying = gEeprom.FM_SelectedFrequency;
-                                BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+ 				 BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
                                 gRequestSaveFM = true;
                                 return;

@@ -290,6 +290,6 @@

                                         gEeprom.FM_FrequencyPlaying = gFM_Channels[Channel];
-                                        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+                                        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
                                         gRequestSaveFM = true;
                                         return;

@@ -337,5 +337,6 @@

+                        // no longer required - cjb
                         // case KEY_2:
                         //      gEeprom.FM_Space = (gEeprom.FM_Space + 1) % 3;
                         //      gRequestSaveFM = true;
                         //      break;

                         case KEY_3:
                                 gEeprom.FM_IsMrMode = !gEeprom.FM_IsMrMode;

                                 if (!FM_ConfigureChannelState()) {
-                                        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+                                        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
                                         gRequestSaveFM = true;
                                 }

@@ -434,10 +435,10 @@

                         if (gAskToDelete) {
                                 gFM_Channels[gEeprom.FM_SelectedChannel] = 0xFFFF;

                                 FM_ConfigureChannelState();
-                                BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+                                BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);
                                 gRequestSaveFM = true;
                         }

@@ -509,5 +510,5 @@

 Bail:
-        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+        BK1080_SetFrequency(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);

         gRequestDisplayScreen = DISPLAY_FM;

@@ -592,8 +593,8 @@
         gFM_RestoreCountdown_10ms = 0;

-        BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band/*, gEeprom.FM_Space*/);
+        BK1080_Init(gEeprom.FM_FrequencyPlaying, gEeprom.FM_Band, gEeprom.FM_Space);

         AUDIO_AudioPathOn();


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/app/menu.c /home/cjb/uvk2cjb/app/menu.c
--- uv-k5-firmware-custom/app/menu.c	2024-06-23 14:06:24.069184668 +1000
+++ /home/cjb/uvk2cjb/app/menu.c	2024-05-31 17:08:24.571923808 +1000
@@ -354,11 +354,25 @@
                 case MENU_BATTYP:
                         *pMin = 0;
                         *pMax = 1;
                         break;

+#ifdef ENABLE_FMRADIO
+    case MENU_FMPREEMP:
+      *pMin = 0;
+      *pMax = ARRAY_SIZE(gSubMenu_FMPREEMP) - 1;
+      break;
+    case MENU_FMSPACING:
+      *pMin = 0;
+      *pMax = ARRAY_SIZE(gSubMenu_FMSPACING) - 1;
+      break;
+    case MENU_FMBAND:
+      *pMin = 0;
+      *pMax = ARRAY_SIZE(gSubMenu_FMBAND) - 1;
+      break;
+#endif

                 case MENU_F1SHRT:
                 case MENU_F1LONG:

@@ -778,11 +793,28 @@

                 case MENU_BATTYP:
                         gEeprom.BATTERY_TYPE = gSubMenuSelection;
                         break;

+#ifdef ENABLE_FMRADIO
+    case MENU_FMPREEMP:
+      gEeprom.FM_Preemp = gSubMenuSelection;
+      gRequestSaveFM = true;
+      break;
+
+    case MENU_FMSPACING:
+      gEeprom.FM_Space = gSubMenuSelection;
+      gRequestSaveFM = true;
+      break;
+
+    case MENU_FMBAND:
+      gEeprom.FM_Band = gSubMenuSelection;
+      gRequestSaveFM = true;
+      break;
+
+#endif

                 case MENU_F1SHRT:
                 case MENU_F1LONG:

@@ -818,8 +851,20 @@

 void MENU_ShowCurrentSetting(void)
 {
         switch (UI_MENU_GetCurrentMenuId())
         {
+#ifdef ENABLE_FMRADIO
+    case MENU_FMPREEMP:
+      gSubMenuSelection = gEeprom.FM_Preemp;
+      break;
+
+    case MENU_FMSPACING:
+      gSubMenuSelection = gEeprom.FM_Space;
+      break;
+
+    case MENU_FMBAND:
+      gSubMenuSelection = gEeprom.FM_Band;
+      break;
+#endif


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/driver/bk1080-regs.h /home/cjb/uvk2cjb/driver/bk1080-regs.h
--- uv-k5-firmware-custom/driver/bk1080-regs.h	2024-06-23 14:06:24.073184722 +1000
+++ /home/cjb/uvk2cjb/driver/bk1080-regs.h	2024-05-29 11:55:36.662660601 +1000
@@ -19,10 +19,11 @@

 enum BK1080_Register_t {
         BK1080_REG_00                       = 0x00U,
         BK1080_REG_02_POWER_CONFIGURATION   = 0x02U,
         BK1080_REG_03_CHANNEL               = 0x03U,
+        BK1080_REG_04_SYSTEM_CONFIGURATION1 = 0x04U,
         BK1080_REG_05_SYSTEM_CONFIGURATION2 = 0x05U,
         BK1080_REG_07                       = 0x07U,
         BK1080_REG_10                       = 0x0AU,
         BK1080_REG_25_INTERNAL              = 0x19U,
 };


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/driver/bk1080.c /home/cjb/uvk2cjb/driver/bk1080.c
--- uv-k5-firmware-custom/driver/bk1080.c	2024-06-23 14:06:24.073184722 +1000
+++ /home/cjb/uvk2cjb/driver/bk1080.c	2024-05-31 13:00:08.102515078 +1000
@@ -17,4 +17,6 @@
 #include "driver/system.h"
+#include "driver/eeprom.h"      /* need access to gEeprom */
+#include "settings.h"           /* " */
 #include "misc.h"

@@ -39,7 +41,7 @@
 uint16_t BK1080_BaseFrequency;
 uint16_t BK1080_FrequencyDeviation;

 void BK1080_Init0(void)
 {
-        BK1080_Init(0,0/*,0*/);
+        BK1080_Init(0,0,0);
 }

-void BK1080_Init(uint16_t freq, uint8_t band/*, uint8_t space*/)
+void BK1080_Init(uint16_t freq, uint8_t band, uint8_t space)
 {
         unsigned int i;

         if (freq) {
                 GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BK1080);
@@ -66,7 +68,12 @@
                 }
                 else {
                         BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0201);
                 }

+ // 0000 1000 0000 0000 .. 15:res 14:STCIEN=0; 13:DEBPS=0; 12:res; 11:DE=0; 10:AGCD=0; 9:8:res; 7:6:BLNDADJ=0; 5:4:GPIO3=0/Low; 3:2:GPIO2=0; 1:0:GPIO0
+               uint16_t tmp04 = gEeprom.FM_Preemp ? 0 : 1<<11;
+               BK1080_WriteRegister(BK1080_REG_04_SYSTEM_CONFIGURATION1, tmp04);
+
+ // 0x0A1F - 00001010 00 01 1111 == volume=1111; channel_spacing= (xx)01; BAND=(xx)00; seek_thresh=0
+               uint16_t tmp05 = 0x0A00 + ((gEeprom.FM_Band & 3) << 6) + ((space & 3) << 4) + 0x00F; // was 0x0A1F
+               BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, tmp05);
+
+    BK1080_SetFrequency(freq, band, space);
         }
         else {
                 BK1080_WriteRegister(BK1080_REG_02_POWER_CONFIGURATION, 0x0241);
  
@@ -103,13 +112,18 @@

-void BK1080_SetFrequency(uint16_t frequency, uint8_t band/*, uint8_t space*/)
+void BK1080_SetFrequency(uint16_t frequency, uint8_t band, uint8_t space)
 {
+        uint8_t spacings[] = {20,10,5};
+        space %= 3;
+
+        uint16_t channel = ((frequency - BK1080_GetFreqLoLimit(band)) * 10) / spacings[space];
+
+        uint16_t regval = BK1080_ReadRegister(BK1080_REG_04_SYSTEM_CONFIGURATION1);
+        regval = (regval & ~(1<<11)) | (gEeprom.FM_Preemp ? 0 : 1<<11);
+        BK1080_WriteRegister(BK1080_REG_04_SYSTEM_CONFIGURATION1, regval);
+
+        regval = BK1080_ReadRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2);
+        regval = (regval & ~(0b11 << 6)) | ((band & 0b11) << 6);
+        regval = (regval & ~(0b11 << 4)) | ((space & 0b11) << 4);
         BK1080_WriteRegister(BK1080_REG_05_SYSTEM_CONFIGURATION2, regval);
         BK1080_WriteRegister(BK1080_REG_03_CHANNEL, channel);
         SYSTEM_DelayMs(10);


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/driver/bk1080.h /home/cjb/uvk2cjb/driver/bk1080.h
--- uv-k5-firmware-custom/driver/bk1080.h	2024-06-23 14:06:24.073184722 +1000
+++ /home/cjb/uvk2cjb/driver/bk1080.h	2024-05-31 12:50:02.100839135 +1000
@@ -23,10 +23,10 @@

 void BK1080_Init0(void);
+void BK1080_Init(uint16_t Frequency, uint8_t band, uint8_t space);
 uint16_t BK1080_ReadRegister(BK1080_Register_t Register);
 void BK1080_WriteRegister(BK1080_Register_t Register, uint16_t Value);
 void BK1080_Mute(bool Mute);
 uint16_t BK1080_GetFreqLoLimit(uint8_t band);
 uint16_t BK1080_GetFreqHiLimit(uint8_t band);
+void BK1080_SetFrequency(uint16_t frequency, uint8_t band, uint8_t space);
 void BK1080_GetFrequencyDeviation(uint16_t Frequency);


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/settings.c /home/cjb/uvk2cjb/settings.c
--- uv-k5-firmware-custom/settings.c	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/settings.c	2024-05-31 12:09:32.166001577 +1000
@@ -116,14 +116,18 @@

                         uint16_t selFreq;
                         uint8_t  selChn;
                         uint8_t  isMrMode:1;
                         uint8_t  band:2;
+                        uint8_t  space:2;
+                        uint8_t  preemp:1;
                 } __attribute__((packed)) fmCfg;
+                EEPROM_ReadBuffer(0x0E88, &fmCfg, sizeof(fmCfg));

                 gEeprom.FM_Band = fmCfg.band;
+                gEeprom.FM_Space = fmCfg.space;
+                gEeprom.FM_Preemp = fmCfg.preemp;

                 gEeprom.FM_SelectedFrequency =
                         (fmCfg.selFreq >= BK1080_GetFreqLoLimit(gEeprom.FM_Band) && fmCfg.selFreq <= BK1080_GetFreqHiLimit(gEeprom.FM_Band)) ?
                                 fmCfg.selFreq : BK1080_GetFreqLoLimit(gEeprom.FM_Band);

@@ -140,15 +142,16 @@
         gEeprom.KEY_1_LONG_PRESS_ACTION      = (Data[2] < ACTION_OPT_LEN) ? Data[2] : ACTION_OPT_NONE;
         gEeprom.KEY_2_SHORT_PRESS_ACTION     = (Data[3] < ACTION_OPT_LEN) ? Data[3] : ACTION_OPT_SCAN;
+        gEeprom.KEY_2_LONG_PRESS_ACTION      = (Data[4] < ACTION_OPT_LEN) ? Data[4] : ACTION_OPT_FM;
         gEeprom.SCAN_RESUME_MODE             = (Data[5] < 3)              ? Data[5] : SCAN_RESUME_CO;
         gEeprom.AUTO_KEYPAD_LOCK             = (Data[6] < 2)              ? Data[6] : false;

         // 0E98..0E9F
         EEPROM_ReadBuffer(0x0E98, Data, 8);

@@ -453,15 +455,19 @@
                         struct {
                                 uint16_t selFreq;
                                 uint8_t  selChn;
                                 uint8_t  isMrMode:1;
                                 uint8_t  band:2;
+                                uint8_t  space:2;
+                                uint8_t  preemp:1;
                         };
                         uint8_t __raw[8];
                 } __attribute__((packed)) fmCfg;

                 memset(fmCfg.__raw, 0xFF, sizeof(fmCfg.__raw));
                 fmCfg.selChn   = gEeprom.FM_SelectedChannel;
                 fmCfg.selFreq  = gEeprom.FM_SelectedFrequency;
                 fmCfg.isMrMode = gEeprom.FM_IsMrMode;
                 fmCfg.band     = gEeprom.FM_Band;
+                fmCfg.space    = gEeprom.FM_Space;
+                fmCfg.preemp   = gEeprom.FM_Preemp;
                 EEPROM_WriteBuffer(0x0E88, fmCfg.__raw);


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/settings.h /home/cjb/uvk2cjb/settings.h
--- uv-k5-firmware-custom/settings.h	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/settings.h	2024-05-31 11:41:42.848329210 +1000

@@ -155,8 +156,10 @@
         uint16_t          FM_SelectedFrequency;
         uint8_t           FM_SelectedChannel;
         bool              FM_IsMrMode;
         uint16_t          FM_FrequencyPlaying;
         uint8_t           FM_Band  : 2;
+        uint8_t  FM_Space : 2;
+        uint8_t  FM_Preemp : 1;
 #endif


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/ui/fmradio.c /home/cjb/uvk2cjb/ui/fmradio.c
--- uv-k5-firmware-custom/ui/fmradio.c	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/ui/fmradio.c	2024-05-19 09:05:52.620001147 +1000
@@ -56,8 +56,8 @@
                         pPrintStr = String;
                 } else {
+                        pPrintStr = "  mhz";
                         for (unsigned int i = 0; i < 20; i++) {
                                 if (gEeprom.FM_FrequencyPlaying == gFM_Channels[i]) {

@@ -87,4 +87,4 @@

+                UI_DisplayFrequency(String, 24, 1, gInputBoxIndex == 0);  // frequency xxx
                 ST7565_BlitFullScreen();
                 return;


This is when the Commodore BigFont is being used..

diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/ui/helper.c /home/cjb/uvk2cjb/ui/helper.c
--- uv-k5-firmware-custom/ui/helper.c	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/ui/helper.c	2024-05-19 15:43:31.872976896 +1000
@@ -143,21 +153,50 @@

 void UI_DisplayFrequency(const char *string, uint8_t X, uint8_t Y, bool center)
 {
+        const unsigned int char_width  = 8;
         uint8_t           *pFb0        = gFrameBuffer[Y] + X;
         uint8_t           *pFb1        = pFb0 + 128;
         bool               bCanDisplay = false;

         uint8_t len = strlen(string);

+        for (int i = 0; i < len; i++)
+        {
+                 char c = string[i];
+                 if (bCanDisplay || c != ' ')
+                 {
+                    bCanDisplay = true;
+                    if (c>='0' /*& c<='9' + 1*/)
+         	        {
+				for (int k = 0; k < 7; k++)
+                		{
+                  		*(pFb0 + 2 + k) = gFontBig[c-'!'][k];
+                  		*(pFb0 + 3 + k) = gFontBig[c-'!'][k];
+                  		*(pFb0 + 4 + k) = gFontBig[c-'!'][k];
+                  		*(pFb1 + 2 + k) = gFontBig[c-'!'][k+7];
+                  		*(pFb1 + 3 + k) = gFontBig[c-'!'][k+7];
+                  		*(pFb1 + 4 + k) = gFontBig[c-'!'][k+7];
+                  		pFb0 += 2;
+                  		pFb1 += 2;
+                		}
+            		}
+          	    else
+            	        if (c == '.')
+                       {
+                	pFb0 += 2;
+                	pFb1 += 2;
                        *pFb1 = 0x60; pFb0++; pFb1++;
                        *pFb1 = 0x60; pFb0++; pFb1++;
+                 	*pFb1 = 0x60;
                        continue;
                         }

                 }
+          else
+              if (center)
+                {
                     pFb0 -= 6;
                     pFb1 -= 6;
                 }
                 pFb0 += char_width;
                 pFb1 += char_width;


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/ui/menu.c /home/cjb/uvk2cjb/ui/menu.c
--- uv-k5-firmware-custom/ui/menu.c	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/ui/menu.c	2024-06-08 14:20:01.982309730 +1000
@@ -117,6 +117,11 @@

 #ifdef ENABLE_VOX
         {"VOX",    VOICE_ID_VOX,                           MENU_VOX           },
 #endif
+#ifdef ENABLE_FMRADIO
+    {"FM Pre", VOICE_ID_INVALID,                       MENU_FMPREEMP      },
+    {"FM Spc", VOICE_ID_INVALID,                       MENU_FMSPACING     },
+    {"FM Bnd", VOICE_ID_INVALID,                       MENU_FMBAND        },
+#endif
         {"BatVol", VOICE_ID_INVALID,                       MENU_VOL           }, // was "VOL"

@@ -141,3 +146,25 @@

+#ifdef ENABLE_FMRADIO
+const char gSubMenu_FMPREEMP[][6] =
+  {
+    "75 uS",
+    "50 uS"
+  };
+
+const char gSubMenu_FMSPACING[][8] =
+  {
+    "200 kHz",
+    "100 kHz",
+    " 50 kHz"
+  };
+
+const char gSubMenu_FMBAND[][9] =
+  {
+    "87.5-108",
+    "76-108",
+    "76-90",
+    "64-76"
+  };
+#endif

@@ -626,7 +656,18 @@
                 case MENU_ABR_ON_TX_RX:
                         strcpy(String, gSubMenu_RX_TX[gSubMenuSelection]);
                         break;

+#if ENABLE_FMRADIO
+    case MENU_FMPREEMP:
+      strcpy (String, gSubMenu_FMPREEMP[gSubMenuSelection]);
+      break;
+    case MENU_FMSPACING:
+      strcpy (String, gSubMenu_FMSPACING[gSubMenuSelection]);
+      break;
+    case MENU_FMBAND:
+      strcpy (String, gSubMenu_FMBAND[gSubMenuSelection]);
+      break;
+#endif

                 case MENU_BCL:
                 case MENU_BEEP:


diff -U5 -t --suppress-blank-empty -r -N -E -Z -b -w -B uv-k5-firmware-custom/ui/menu.h /home/cjb/uvk2cjb/ui/menu.h
--- uv-k5-firmware-custom/ui/menu.h	2024-06-23 14:06:24.297187760 +1000
+++ /home/cjb/uvk2cjb/ui/menu.h	2024-05-31 17:05:05.935240700 +1000
@@ -121,7 +121,13 @@

         MENU_F2LONG,
         MENU_MLONG,
+#ifdef ENABLE_FMRADIO
+    MENU_FMPREEMP,
+    MENU_FMSPACING,
+    MENU_FMBAND,
+#endif
+    MENU_BATTYP
 };

@@ -156,5 +161,10 @@

 extern const char        gSubMenu_BATTYP[2][9];
 extern const char        gSubMenu_SCRAMBLER[11][7];

+#ifdef ENABLE_FMRADIO
+extern const char gSubMenu_FMPREEMP[2][6];
+extern const char gSubMenu_FMSPACING[3][8];
+extern const char gSubMenu_FMBAND[4][9];
+#endif

